#include "plc.h"

Plc::Plc(QObject *parent) : QObject(parent)
{
    Init();
    ConnectPrepare();
}

Plc::~Plc()
{
    _rw_timer->stop();
    _reconnect_timer->stop();
    if (_s7client.Connected()) {
        _s7client.Disconnect();
    }
    qDebug()<<"~Plc()";
}

void Plc::Init()
{
    _reconnect_times=0;
    _connect_flag=false;

    _reconnect_timer=new QTimer(this);
    _reconnect_timer->setInterval(RECONNECT_INTERVAL);

    _rw_timer=new QTimer(this);
    _rw_timer->setInterval(PLC_READ_CYCLE);
    connect(_rw_timer, &QTimer::timeout, this, &Plc::RWData);
}


void Plc::ConnectPrepare()
{
    //连接成功
    connect(this, &Plc::connected, this, [ = ]() {
        qInfo() << "PLC连接成功";
        _connect_flag = true;
        _reconnect_timer->stop();
        _reconnect_times = 0;
        _rw_timer->start();
    });

    //重连
    connect(_reconnect_timer, &QTimer::timeout, this, [ = ]() {
        _reconnect_times++;
        int result = _s7client.ConnectTo(PLC_IP, PLC_RACK_NUMBER, PLC_SLOT_NUMBER);
        if (result!=0) {
            qCritical() << "重连PLC失败,次数：" << _reconnect_times;
        }
    });
}

void Plc::ConnectToPlc()
{
    int result = _s7client.ConnectTo(PLC_IP, PLC_RACK_NUMBER, PLC_SLOT_NUMBER);
    if (result != 0) {
        qCritical() << "PLC连接失败! err msg : " << CliErrorText(result).data();
        _reconnect_timer->start(RECONNECT_INTERVAL);
    } else{
        emit connected();
    }
}

void Plc::PauseReqVision(const bool &res)
{
    QMutexLocker lock(&g_rw_mtx);
    if(res){
        g_fromplc_data.cold_vision = true;
        g_fromplc_data.hot_vision = true;
        _recv_vision = false;
    }else{
        g_fromplc_data.cold_vision = false;
        g_fromplc_data.hot_vision = false;
        _recv_vision = true;
    }
}


//读写一体
void Plc::RWData()
{
    if (!_connect_flag) {
        return;
    }
    //qDebug()<<"-------------交互数据!-------------";

    /*
        中间炉门2电脑时钟信号 DB476.DBX0.6 - 主动发送，0.5s更新数据0、1之间
        三层中间炉门2启动信号:DB476.DBX2.5 判断信号:DB476.DBX0.5
    */
    QMutexLocker guard(&g_rw_mtx);



    static int heart_count = 0;
    static int heart = 0;

    //心跳
    if(heart_count==5) { //0.5s更新1次时钟信号
        heart_count = 0;
        if(heart == 0){
            heart = 1;
        }else{
            heart = 0;
        }
    }
    heart_count++;

    unsigned char DB476_0=0; //数据段476，第0个字节
    unsigned char DB476_2 = 0;

    //read
    _s7client.DBRead(476, 2, 1, &DB476_2); //DBRead(数据块，具体字节，读取数量，out)
    if(_recv_vision) {
        g_fromplc_data.hot_vision =(DB476_2>>5) & 0x1; // xx>>n & 0x01, 只取第n位；移到末位，再乘以0x0000001; //获取视觉请求信号
        g_fromplc_data.cold_vision =(DB476_2>>4) & 0x1;
    }

    //write
    DB476_0 = (heart==0) ? (DB476_0 | (1 << 6)) : (DB476_0 & (~(1 << 6))); //1<<n，第n位设置为1；第n位设置为0
    DB476_0 = (g_toplc_data.hot_product==0) ? (DB476_0 & (~(1 << 5))) : (DB476_0 | (1 << 5));
    DB476_0 = (g_toplc_data.cold_product==0) ? (DB476_0 & (~(1 << 4))) : (DB476_0 | (1 << 4));
    _s7client.DBWrite(476,0,1,&DB476_0);//DBRead(数据块，具体字节，写入数量，out)

    //qDebug() << "DB476_2:" << QString::number(DB476_2, 2).rightJustified(8, '0');
    //qDebug() << "DB476_0:" << QString::number(DB476_0, 2).rightJustified(8, '0');
}


